import dayjs from "dayjs";
/**
 * 判断是否为函数
 *
 * @param {*} obj
 * @return {*}
 */
const isFunction = (obj) => {
  return (
    typeof obj === "function" &&
    typeof obj.nodeType !== "number" &&
    typeof obj.item !== "function"
  );
};
/**
 * 节流防抖操作
 *
 * @param {*} fn 函数
 * @param {*} delay 时间
 * @return {*}
 */
function debounce(fn, delay) {
  let timer = null; // 用于保存定时器
  return function () {
    // 如果timer存在 就清除定时器，重新计时
    if (timer) {
      clearTimeout(timer);
    }
    //设置定时器，规定时间后执行真实要执行的函数
    timer = setTimeout(() => {
      fn.apply(this);
    }, delay);
  };
}

/**
 * 节流函数
 *
 * @param {*} fn 函数
 * @return {*}
 */
function throttle(fn) {
  let timer = null; // 首先设定一个变量，没有执行定时器时,默认为 null
  return function () {
    if (timer) return; // 当定时器没有执行的时候timer永远是false,后面无需执行
    timer = setTimeout(() => {
      fn.apply(this, arguments);
      // 最后在setTimeout执行完毕后再把标记设置为true(关键)
      // 表示可以执行下一次循环了。
      timer = null;
    }, 1000);
  };
}

/**
 * 根据传入数值大小转换为空间字符串
 * @param {Object} bytes
 */
function formatBytes(bytes) {
  const sizes = ["B", "KB", "MB", "GB", "TB"];
  if (bytes == 0) {
    return "n/a";
  }
  const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
  if (i == 0) {
    return bytes + " " + sizes[i];
  }
  return (bytes / Math.pow(1024, i)).toFixed(1) + " " + sizes[i];
}

function groupBy(arr = [], key) {
  let mapObj = {};
  arr.forEach((item) => {
    let groupKey = item[key] || "default";
    let childrenArray = mapObj[groupKey] || (mapObj[groupKey] = []);
    childrenArray.push(item);
  });
  return mapObj;
}

function objClear(obj) {
  Object.keys(obj).forEach((key) => {
    if (!obj[key] && obj[key] != 0) {
      delete obj[key];
    }
    if (obj[key] == "") {
      delete obj[key];
    }
  });
  return obj;
}

function objAssignOfNull(target, assObj) {
  for (let key in assObj) {
    if (!target[key] && target[key] !== false) {
      target[key] = assObj[key];
    }
  }
}

function dateStr(date = new Date()) {
  return dayjs(date).format("YYYY-MM-DD HH:mm:ss");
}

const eventBus = {};

function emitEvent(code, data) {
  eventBus[code].forEach((item) => item(data));
}

function onEvent(code, fun) {
  eventBus[code] = eventBus[code] || [];
  eventBus[code] = [...eventBus[code], fun];
}

export default {
  isString: (str) => typeof str === "string" || str instanceof String,
  isNumberStr: (str) => /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str),
  formatBytes,
  groupBy,
  objClear,
  emitEvent,
  onEvent,
  objAssignOfNull,
  debounce,
  isFunction,
  throttle,
  dateStr,
};
